package com.dy.yunying.biz.service.hongbao.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dy.yunying.api.entity.hongbao.HbActivity;
import com.dy.yunying.api.entity.hongbao.HbCashConfig;
import com.dy.yunying.api.entity.hongbao.HbGiftBag;
import com.dy.yunying.api.entity.hongbao.HbReceivingRecord;
import com.dy.yunying.api.enums.CashTypeEnum;
import com.dy.yunying.api.enums.HbRedpackTypeEnum;
import com.dy.yunying.api.req.hongbao.CashConfigReq;
import com.dy.yunying.api.resp.hongbao.CashConfigVo;
import com.dy.yunying.api.resp.hongbao.GiftData;
import com.dy.yunying.api.utils.CheckUtils;
import com.dy.yunying.api.utils.FileUtils;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityGameMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbActivityMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbCashConfigMapper;
import com.dy.yunying.biz.dao.ads.hongbao.HbGiftBagMapper;
import com.dy.yunying.biz.service.hongbao.CashConfigService;
import com.dy.yunying.biz.service.hongbao.HbGiftBagService;
import com.dy.yunying.biz.service.hongbao.HbReceivingRecordService;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.util.CommonUtils;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author yuwenfeng
 * @description: 提现档次服务
 * @date 2021/10/23 15:39
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CashConfigServiceImpl extends ServiceImpl<HbCashConfigMapper, HbCashConfig> implements CashConfigService {
	private final HbCashConfigMapper cashConfigMapper;

	private final HbGiftBagMapper giftBagMapper;

	private final HbGiftBagService hbGiftBagService;

	private final HbActivityGameMapper activityGameMapper;

	private final HbReceivingRecordService hbReceivingRecordService;

	private final HbActivityMapper hbActivityMapper;

	@Override
	public Page<CashConfigVo> selectCashConfigPage(Page<HbCashConfig> page, QueryWrapper<HbCashConfig> query) {
		Page<CashConfigVo> voPage = cashConfigMapper.selectVoPage(page, query);
		if (CollectionUtils.isNotEmpty(voPage.getRecords())) {
			List<Long> ids = voPage.getRecords().stream().map(CashConfigVo::getId).collect(Collectors.toList());
			List<GiftData> giftList = giftBagMapper.selectGroupCodeList(2, 1, ids);
			for (CashConfigVo vo : voPage.getRecords()) {
				if (CashTypeEnum.GameMoney.getType().equals(vo.getCashType())) {
					if (CollectionUtils.isNotEmpty(giftList)) {
						for (GiftData giftData : giftList) {
							if (vo.getId().equals(giftData.getGiftId())) {
								vo.setGiftBagCodes(giftData.getGiftCodes());
							}
						}
					}
				}
				if (CashTypeEnum.Cdk.getType().equals(vo.getCashType())) {
					vo.setCdkAmount(new BigDecimal(vo.getCdkAmount()).setScale(0).toString());
					vo.setCdkLimitAmount(new BigDecimal(vo.getCdkLimitAmount()).setScale(0).toString());
				}
			}
		}
		return voPage;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R addCashConfig(CashConfigReq cashConfig) {
		R result = R.ok();
		HbCashConfig info = new HbCashConfig();
		info.setSubscriptOff(cashConfig.getSubscriptOff());
		if (null != cashConfig.getSubscriptOff() && cashConfig.getSubscriptOff() == 1) {
			if (StringUtils.isBlank(cashConfig.getSubscriptName())) {
				return R.failed("角标内容不能为空");
			}
			String subscriptName = cashConfig.getSubscriptName().trim();
			if (subscriptName.length() > 4) {
				return R.failed("角标内容太长");
			}
			info.setSubscriptName(subscriptName);
		}
		if (null == cashConfig.getActivityId() || cashConfig.getActivityId() <= 0) {
			return R.failed("活动ID不能为空");
		}
		info.setActivityId(cashConfig.getActivityId());
		if (null == cashConfig.getCashType() || cashConfig.getCashType() <= 0) {
			return R.failed("提现类型不能为空");
		}
		String cashName = cashConfig.getCashName().trim();
		int chkNum = cashConfigMapper.selectCount(new QueryWrapper<HbCashConfig>()
				.eq("activity_id", cashConfig.getActivityId())
				.eq("cash_type", cashConfig.getCashType())
				.eq("cash_name", cashName));
		if (chkNum > 0) {
			return R.failed(cashName + "已存在，无法继续添加");
		}
		info.setCashType(cashConfig.getCashType());
		info.setCashName(cashName);
		info.setCashMoney(cashConfig.getCashMoney());
		info.setCreateTime(new Date());
		info.setCreateId(SecurityUtils.getUser().getId().longValue());
		info.setUpdateTime(new Date());
		info.setUpdateId(SecurityUtils.getUser().getId().longValue());
		if (CashTypeEnum.GameMoney.getType().equals(cashConfig.getCashType())) {
			//判断活动范围是否有多个父游戏
			List<Long> pGameList = activityGameMapper.selectGroupPgIdByActivityId(info.getActivityId());
			if (CollectionUtils.isNotEmpty(pGameList) && pGameList.size() > 1) {
				return R.failed("多个父游戏时，不能选择游戏货币");
			}
			if (Objects.isNull(cashConfig.getGiftType())) {
				return R.failed("请选择礼包码类型");
			}
			info.setGiftType(cashConfig.getGiftType());
			// 礼包唯一码
			if (1 == cashConfig.getGiftType().intValue()) {
				if (null == cashConfig.getFile() || cashConfig.getFile().isEmpty()) {
					return R.failed("游戏币的礼包码不能为空");
				}
			} else if (2 == cashConfig.getGiftType().intValue()) {
				String giftAmount = cashConfig.getGiftAmount();
				String giftCode = cashConfig.getGiftCode();
				if (StringUtils.isBlank(giftCode)) {
					return R.failed("请输入通用礼包码");
				}
				if (StringUtils.isBlank(giftAmount)) {
					return R.failed("请输入礼包码数量");
				}
				String regex = "^[A-Za-z0-9]+$";
				if (giftCode.length() < 3 || giftCode.length() > 50 || !giftCode.matches(regex)) {
					return R.failed("通用礼包码应为3~50个英文大小写或数字组成");
				}
				if (!CheckUtils.checkInt(giftAmount)) {
					return R.failed("请输入有效的礼包数量");
				}
				if (giftAmount.length() > 7 || Integer.valueOf(giftAmount) < 0 || Integer.valueOf(giftAmount) > 9999999) {
					return R.failed("礼包数量应为0~9999999");
				}
				info.setGiftCode(giftCode);
				info.setGiftAmount(Integer.valueOf(giftAmount));
			}
		} else if (CashTypeEnum.Cdk.getType().equals(cashConfig.getCashType())) {
			R check = this.baseCheck(cashConfig);
			if (check.getCode() == CommonConstants.FAIL) {
				return check;
			}
			info.setCdkName(cashConfig.getCdkName());
			info.setCdkAmount(cashConfig.getCdkAmount());
			info.setCdkLimitAmount(cashConfig.getCdkLimitAmount());
			info.setExpiryType(cashConfig.getExpiryType());
			if (cashConfig.getExpiryType() == 2) {
				info.setStartTime(cashConfig.getStartTime());
				info.setEndTime(cashConfig.getEndTime());
			}
			info.setDays(cashConfig.getDays());
			info.setCdkLimitType(cashConfig.getCdkLimitType());
		} else if (CashTypeEnum.BALANCE.getType().equals(info.getCashType())) {
			String currencyAmount = cashConfig.getCurrencyAmount();
			if (StringUtils.isBlank(currencyAmount)) {
				return R.failed("提现游豆不能为空");
			}
			if (!CommonUtils.isMoney(currencyAmount, 3)) {
				return R.failed("提现游豆格式不正确");
			}
			info.setCurrencyAmount(new BigDecimal(currencyAmount));
		}
		cashConfigMapper.insert(info);
		if (CashTypeEnum.GameMoney.getType().equals(cashConfig.getCashType())) {
			// 礼包唯一码
			if (1 == cashConfig.getGiftType().intValue()) {
				result = addCashGiftBag(cashConfig.getFile(), info.getId());
				if (!CommonConstants.SUCCESS.equals(result.getCode())) {
					return result;
				}
			} else if (2 == cashConfig.getGiftType().intValue()) {
				result = addCommonGift(info);
				if (!CommonConstants.SUCCESS.equals(result.getCode())) {
					return result;
				}
			}
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R editCashConfig(CashConfigReq cashConfig) {
		R result = R.ok();
		if (null == cashConfig.getId() || cashConfig.getId() <= 0) {
			return R.failed("提现档次ID不能为空");
		}
		if (null != cashConfig.getSubscriptOff() && cashConfig.getSubscriptOff() == 1) {
			if (StringUtils.isBlank(cashConfig.getSubscriptName())) {
				return R.failed("角标内容不能为空");
			}
		}
		String cashName = cashConfig.getCashName().trim();
		HbCashConfig info = cashConfigMapper.selectById(cashConfig.getId());
		if (null == info) {
			return R.failed("提现档次不存在");
		}
		if (null != cashConfig.getSubscriptOff() && cashConfig.getSubscriptOff() == 1) {
			if (StringUtils.isBlank(cashConfig.getSubscriptName())) {
				return R.failed("角标内容不能为空");
			}
			String subscriptName = cashConfig.getSubscriptName().trim();
			if (subscriptName.length() > 4) {
				return R.failed("角标内容太长");
			}
			info.setSubscriptName(subscriptName);
		}
		info.setSubscriptOff(cashConfig.getSubscriptOff());
		info.setCashName(cashName);
		info.setCashMoney(cashConfig.getCashMoney());
		info.setUpdateTime(new Date());
		info.setUpdateId(SecurityUtils.getUser().getId().longValue());
		List<HbCashConfig> oldList = cashConfigMapper.selectList(new QueryWrapper<HbCashConfig>()
				.eq("activity_id", info.getActivityId())
				.eq("cash_type", info.getCashType())
				.eq("cash_name", cashName));
		if (CollectionUtils.isNotEmpty(oldList)) {
			for (HbCashConfig old : oldList) {
				if (!info.getId().equals(old.getId())) {
					return R.failed(cashName + "已存在，无法编辑");
				}
			}
		}
		if (CashTypeEnum.GameMoney.getType().equals(info.getCashType())) {
			//判断活动范围是否有多个父游戏
			List<Long> pGameList = activityGameMapper.selectGroupPgIdByActivityId(info.getActivityId());
			if (CollectionUtils.isNotEmpty(pGameList) && pGameList.size() > 1) {
				return R.failed("多个父游戏时，不能选择游戏货币");
			}
			if (Objects.isNull(cashConfig.getGiftType())) {
				return R.failed("请选择礼包码类型");
			}
			info.setGiftType(cashConfig.getGiftType());
			// 礼包通用码
			if (2 == cashConfig.getGiftType().intValue()) {
				String giftAmount = cashConfig.getGiftAmount();
				String giftCode = cashConfig.getGiftCode();
				if (StringUtils.isBlank(giftCode)) {
					return R.failed("请输入通用礼包码");
				}
				if (StringUtils.isBlank(giftAmount)) {
					return R.failed("请输入礼包码数量");
				}
				String regex = "^[A-Za-z0-9]+$";
				if (giftCode.length() < 3 || giftCode.length() > 50 || !giftCode.matches(regex)) {
					return R.failed("通用礼包码应为3~50个英文大小写或数字组成");
				}
				if (!CheckUtils.checkInt(giftAmount)) {
					return R.failed("请输入有效的礼包数量");
				}
				if (giftAmount.length() > 7 || Integer.valueOf(giftAmount) < 0 || Integer.valueOf(giftAmount) > 9999999) {
					return R.failed("礼包数量应为0~9999999");
				}
				info.setGiftCode(giftCode);
				info.setGiftAmount(Integer.valueOf(giftAmount));
			}
			if (1 == cashConfig.getGiftType().intValue() && null != cashConfig.getFile() && !cashConfig.getFile().isEmpty()) {
				result = addCashGiftBag(cashConfig.getFile(), info.getId());
				if (!CommonConstants.SUCCESS.equals(result.getCode())) {
					return result;
				}
			} else if (2 == cashConfig.getGiftType().intValue()) {
				result = addCommonGift(info);
				if (!CommonConstants.SUCCESS.equals(result.getCode())) {
					return result;
				}
			}
		} else if (CashTypeEnum.Cdk.getType().equals(info.getCashType())) {
			cashConfig.setActivityId(info.getActivityId());
			R check = this.baseCheck(cashConfig);
			if (check.getCode() == CommonConstants.FAIL) {
				return check;
			}
			info.setCdkName(cashConfig.getCdkName());
			info.setCdkAmount(cashConfig.getCdkAmount());
			info.setCdkLimitAmount(cashConfig.getCdkLimitAmount());
			info.setExpiryType(cashConfig.getExpiryType());
			if (cashConfig.getExpiryType() == 2) {
				info.setStartTime(cashConfig.getStartTime());
				info.setEndTime(cashConfig.getEndTime());
			}
			info.setDays(cashConfig.getDays());
			info.setCdkLimitType(cashConfig.getCdkLimitType());
		} else if (CashTypeEnum.BALANCE.getType().equals(info.getCashType())) {
			String currencyAmount = cashConfig.getCurrencyAmount();
			if (StringUtils.isBlank(currencyAmount)) {
				return R.failed("提现游豆不能为空");
			}
			if (!CommonUtils.isMoney(currencyAmount, 3)) {
				return R.failed("提现游豆格式不正确");
			}
			info.setCurrencyAmount(new BigDecimal(currencyAmount));
		}
		cashConfigMapper.updateById(info);
		return result;
	}

	private R baseCheck(CashConfigReq dto) {
		if (StringUtils.isBlank(dto.getCdkName())) {
			return R.failed("代金券名称不能为空");
		}
		if (dto.getCdkName().trim().length() > 16) {
			return R.failed("代金券名称长度不能超过16");
		}

		if (StringUtils.isBlank(dto.getCdkAmount())) {
			return R.failed("代金券金额不能为空");
		}

		if (!CommonUtils.isMoney(dto.getCdkAmount(), 0)) {
			return R.failed("代金券金额格式不正确");
		}

		if (dto.getCdkAmount().trim().length() > 6) {
			return R.failed("代金券金额长度不能超过6位");
		}

		if (StringUtils.isBlank(dto.getCdkLimitAmount())) {
			return R.failed("满可用金额不能为空");
		}

		if (!CommonUtils.isMoney(dto.getCdkLimitAmount(), 0)) {
			return R.failed("满可用金额格式不正确");
		}

		if (dto.getCdkLimitAmount().trim().length() > 6) {
			return R.failed("满可用金额长度不能超过6位");
		}

		BigDecimal cdkAmount = new BigDecimal(dto.getCdkAmount());
		BigDecimal cdkLimitAmount = new BigDecimal(dto.getCdkLimitAmount());
		if (cdkLimitAmount.compareTo(cdkAmount) <= 0) {
			return R.failed("满可用金额必须大于代金券金额");
		}

		if (dto.getExpiryType() == null) {
			return R.failed("有效规则不能为空");
		}

		if (dto.getExpiryType() == 2) {
			if (StringUtils.isBlank(dto.getStartTime())) {
				return R.failed("开始时间不能为空");
			}
			if (StringUtils.isBlank(dto.getEndTime())) {
				return R.failed("结束时间不能为空");
			}
			//校验开始时间 >= 领取时间
			Date sDate = DateUtil.parse(dto.getStartTime(), "yyyy-MM-dd");
			Date eDate = DateUtil.parse(dto.getEndTime(), "yyyy-MM-dd");
			//获取活动基本信息
			HbActivity activity = hbActivityMapper.selectById(dto.getActivityId());
			if (activity != null) {
				if (sDate.compareTo(activity.getStartTime()) < 0) {
					return R.failed("开始时间不能小于活动开始时间" + DateUtil.format(activity.getStartTime(), "yyyy-MM-dd"));
				}
			} else {
				return R.failed("活动不存在");
			}

			if (eDate.compareTo(sDate) < 0) {
				return R.failed("结束时间不能小于开始时间");
			}

		}

		if (dto.getExpiryType() == 3 && dto.getDays() == null) {
			return R.failed("有效天数不能为空");
		}

		if (null == dto.getCdkLimitType() || dto.getCdkLimitType() < 1) {
			return R.failed("代金券限制类型不能为空");
		}
		return R.ok();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R delCashConfig(Long cashConfigId) {
		HbCashConfig info = cashConfigMapper.selectById(cashConfigId);
		if (null == info) {
			return R.failed("提现档次不存在");
		}
		cashConfigMapper.deleteById(info.getId());
		return R.ok();
	}

	@Transactional(rollbackFor = Exception.class)
	R addCashGiftBag(MultipartFile file, Long objectId) {
		if (!file.isEmpty()) {
			long fileSize = file.getSize();
			if (fileSize < 3 || fileSize > 1048576) {
				throw new RuntimeException("礼包码文件大小应在3字节~1M之间");
			}
			// 获取名称
			String filename = file.getOriginalFilename();
			// 获取后缀名
			String suffix = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
			if (!"txt".equalsIgnoreCase(suffix)) {
				throw new RuntimeException("请上传txt格式的礼包码文件");
			}
			List<String> readList = FileUtils.readFileContent(file);
			if (CollectionUtils.isEmpty(readList)) {
				throw new RuntimeException("读取礼包码信息失败");
			}
			List<String> list = readList.stream().distinct().collect(Collectors.toList());
			list = list.stream().filter(item -> item.trim().length() >= 3 && item.trim().length() <= 50).collect(Collectors.toList());
			List<HbGiftBag> saveList = new ArrayList<HbGiftBag>();
			if (CollectionUtils.isNotEmpty(list)) {
				QueryWrapper<HbGiftBag> wrapper = new QueryWrapper<>();
				wrapper.in("gift_code", list);
				wrapper.eq("deleted", 0);
				List<HbGiftBag> resultList = hbGiftBagService.list(wrapper);
				HbGiftBag info;
				String regex = "^[A-Za-z0-9]+$";
				for (String str : list) {
					if (StringUtils.isNotBlank(str) && str.length() > 0) {
						String code = str.trim();
						if (CollectionUtils.isNotEmpty(resultList)) {
							int num = resultList.stream().filter(item -> code.equals(item.getGiftCode())).collect(Collectors.toList()).size();
							if (num > 0) {
								continue;
							}
						}
						if (!code.matches(regex)) {
							continue;
						}
						info = new HbGiftBag();
						info.setType(2);
						info.setObjectId(objectId);
						info.setGiftCode(code);
						info.setCreateTime(new Date());
						info.setUpdateTime(new Date());
						info.setCreateId(Long.valueOf(SecurityUtils.getUser().getId()));
						info.setUpdateId(SecurityUtils.getUser().getId().longValue());
						saveList.add(info);
					}
				}
			}
			if (CollectionUtils.isNotEmpty(saveList)) {
				hbGiftBagService.saveBatch(saveList);
			}
			int giftBagSize = saveList.size();
			return R.ok(0, "操作成功，礼包码上传成功：" + giftBagSize + "个，重复无效过滤：" + (readList.size() - giftBagSize) + "个");
		} else {
			throw new RuntimeException("礼包码文件不能为空");
		}
	}

	/**
	 * 更新通用礼包码信息
	 *
	 * @param cashConfig
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public R addCommonGift(HbCashConfig cashConfig) {
		int count = hbReceivingRecordService.count(Wrappers.<HbReceivingRecord>lambdaQuery()
				.eq(HbReceivingRecord::getActivityId, cashConfig.getActivityId())
				.eq(HbReceivingRecord::getObjectType, 2)
				.eq(HbReceivingRecord::getObjectId, cashConfig.getId())
				.eq(HbReceivingRecord::getType, HbRedpackTypeEnum.GIFT.getType())
				.eq(HbReceivingRecord::getGiftCode, cashConfig.getGiftCode()));

		HbGiftBag hbGiftBag = hbGiftBagService.getOne(Wrappers.<HbGiftBag>lambdaQuery()
				.eq(HbGiftBag::getType, 2)
				.eq(HbGiftBag::getObjectId, cashConfig.getId())
				.eq(HbGiftBag::getGiftCode, cashConfig.getGiftCode())
				.last("limit 1")
		);

		if (Objects.isNull(hbGiftBag)) {
			HbGiftBag giftBag = new HbGiftBag();
			giftBag.setType(2);
			giftBag.setObjectId(cashConfig.getId());
			giftBag.setGiftCode(cashConfig.getGiftCode());
			giftBag.setGiftAmount(cashConfig.getGiftAmount());
			giftBag.setGiftGetcounts(count);
			giftBag.setUsable(2);
			giftBag.setCreateTime(new Date());
			giftBag.setUpdateTime(new Date());
			giftBag.setCreateId(Long.valueOf(SecurityUtils.getUser().getId()));
			hbGiftBagService.save(giftBag);
		} else {
			HbGiftBag updateGift = new HbGiftBag();
			updateGift.setId(hbGiftBag.getId());
			updateGift.setGiftAmount(cashConfig.getGiftAmount());
			updateGift.setGiftGetcounts(count);
			updateGift.setDeleted(0);
			hbGiftBagService.updateById(updateGift);
		}
		return R.ok(cashConfig);
	}
}
